package cloud.mybatisplus.generator;

import cloud.mybatisplus.generator.constant.YGT_MED;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * <p>
 * 代码生成器演示
 * </p>
 *
 * @author hubin
 * @date 2016-12-01
 */
public class MPMysqlYgtHospitalGenerator {

    private static final String JDBC_URL = "jdbc:mysql://10.10.0.145:3306/hiscloud?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8";
    private static final String USERNAME = "his-cloud";
    private static final String PASSWORD = "his-cloud";

    public static void main(String[] args) {
        String outputDir = "D:\\dev-projects\\module-service-thirdparty-service\\src\\main\\java";
        String[] tablePrefix = new String[]{"v_"};
        String[] exclude = new String[0];

        generator(outputDir, "third.ygt.med", tablePrefix, YGT_MED.tables, exclude);

    }

    private static void generator(String outputDir, String moduleName, String[] tablePrefix, String[] include, String[] exclude) {
        ExecutorService executor = Executors.newCachedThreadPool();
        executor.execute(() -> generator0(outputDir, moduleName, tablePrefix, include, exclude));
    }

    /**
     * <p>
     * MySQL 生成演示
     * </p>
     */
    private static void generator0(String outputDir, String moduleName, String[] tablePrefix, String[] include, String[] exclude) {
        // 自定义需要填充的字段
        List<TableFill> tableFillList = new ArrayList<>();
        tableFillList.add(new TableFill("ASDD_SS", FieldFill.INSERT_UPDATE));

        // 代码生成器
        AutoGenerator mpg = new AutoGenerator()
                //
                .setGlobalConfig(
                        // 全局配置
                        new GlobalConfig().setOutputDir(outputDir)// 输出目录
                                .setFileOverride(true)// 是否覆盖文件
                                .setActiveRecord(false)// 开启 activeRecord 模式
                                .setEnableCache(false)// XML 二级缓存
                                .setBaseResultMap(true)// XML ResultMap
                                .setBaseColumnList(false)// XML columList
                                // .setKotlin(true) 是否生成 kotlin 代码
                                .setAuthor("liubingjun <br> " + DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"))
                                // 自定义文件命名，注意 %s 会自动填充表实体属性！
                                .setMapperName("%sDao")
                                .setXmlName("%sDao")
                                // .setServiceName("MP%sService")
                                // .setServiceImplName("%sServiceDiy")
                                // .setControllerName("%sAction")
                                .setDateType(DateType.ONLY_DATE)
                        //
                )
                .setDataSource(
                        // 数据源配置
                        new DataSourceConfig().setDbType(DbType.MYSQL)// 数据库类型
                                .setTypeConvert(new MySqlTypeConvert() {
                                    // 自定义数据库表字段类型转换【可选】
                                    @Override
                                    public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
                                        // System.out.println("转换类型：" + fieldType);
                                        // if ( fieldType.toLowerCase().contains( "tinyint" ) ) {
                                        // return DbColumnType.BOOLEAN;
                                        // }
                                        String t = fieldType.toLowerCase();
                                        if (t.contains("tinyint(1)")) {
                                            return new IColumnType() {
                                                @Override
                                                public String getType() {
                                                    return "BooleanEnum";
                                                }

                                                @Override
                                                public String getPkg() {
                                                    return "com.yrd.framework.enums.BooleanEnum";
                                                }
                                            };
                                        }
                                        return super.processTypeConvert(globalConfig, fieldType);
                                    }
                                })//
                                .setDriverName("com.mysql.cj.jdbc.Driver")//
                                .setUsername(USERNAME)
                                .setPassword(PASSWORD)//
                                .setUrl(JDBC_URL)
                        //
                )
                .setStrategy(
                        // 策略配置
                        new StrategyConfig()
                                // .setCapitalMode(true)// 全局大写命名
                                // .setDbColumnUnderline(true)//全局下划线命名
                                //.setTablePrefix(tablePrefix)// 此处可以修改为您的表前缀
                                .setNaming(NamingStrategy.underline_to_camel)// 表名生成策略
                                .setInclude(include) // 需要生成的表
                                .setExclude(exclude) // 排除生成的表
                                // 自定义实体父类
                                // .setSuperEntityClass("com.yrd.his.cloud.thirdparty.huhhot.ygtjcpt.service.BaseEntity")
                                // .setSuperEntityClass(null)
                                // .setSuperEntityColumns("gmt_create", "gmt_modified", "creator", "modifier")
                                // 自定义实体，公共字段
                                // .setSuperEntityColumns(new String[] { "test_id" }).setTableFillList(tableFillList)
                                // 自定义 mapper 父类
                                .setSuperMapperClass("com.yrd.framework.mybatisplus.IBaseDao")
                                // 自定义 service 父类
                                .setSuperServiceClass("com.yrd.framework.mybatisplus.IBaseService")
                                // .setSuperServiceClass("com.yrd.his.cloud.thirdparty.huhhot.ygtjcpt.service.IBaseService")
                                // 自定义 service 实现类父类
                                .setSuperServiceImplClass("com.yrd.framework.mybatisplus.BaseServiceImpl")
                                // .setSuperServiceImplClass("com.yrd.his.cloud.thirdparty.huhhot.ygtjcpt.service.BaseServiceImpl")
                                // 自定义 controller 父类
                                // .setSuperControllerClass("com.yrd.framework.web.controller.BaseCRUDController")
                                // 【实体】是否生成字段常量（默认 false）
                                // public static final String ID = "test_id";
                                // .setEntityColumnConstant(true)
                                // 【实体】是否为构建者模型（默认 false）
                                // public User setName(String name) {this.name = name; return this;}
                                // .setEntityBuilderModel(true)
                                // 【实体】是否为lombok模型（默认 false）<a href="https://projectlombok.org/">document</a>
                                .setEntityLombokModel(true)
                                // Boolean类型字段是否移除is前缀处理
                                // .setEntityBooleanColumnRemoveIsPrefix(true)
                                // .setRestControllerStyle(true)
                                // .setControllerMappingHyphenStyle(true)
                                .setEntityTableFieldAnnotationEnable(true)
                                .setRestControllerStyle(true)
                        //
                )
                .setPackageInfo(
                        // 包配置
                        new PackageConfig().setModuleName(moduleName)
                                .setParent("com.yrd.his.cloud")// 自定义包路径
                                .setEntity("model")
                                .setMapper("dao")
                                .setController("web.controller")// 这里是控制器包名，默认 web
                        //
                )
                .setCfg(
                        // 注入自定义配置，可以在 VM 中使用 cfg.abc 设置的值
                        new InjectionConfig() {
                            @Override
                            public void initMap() {
                                Map<String, Object> map = new HashMap<>();
                                map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
                                map.put("moduleName", moduleName);
                                map.put("packageModuleName", moduleName);
                                map.put("packageParent", "com.yrd.his.cloud");
                                map.put("packageWebParent", "com.yrd.yljk.ggws.web");
                                map.put("packageValidationParent", "com.yrd.yljk.ggws.cgi.validation");
                                this.setMap(map);
                            }
                        }.setFileOutConfigList(Arrays.asList(new FileOutConfig("/templates/mapper.xml.vm") {
                                                                 // 自定义输出文件目录
                                                                 @Override
                                                                 public String outputFile(TableInfo tableInfo) {
                                                                     return outputDir + "/mapper/" + moduleName.replace(".", "/") + "/" + tableInfo.getEntityName() + ".xml";
                                                                 }
                                                             },
                                // new FileOutConfig("/templates/entityVO.java.vm") {
                                // @Override
                                // public String outputFile(TableInfo tableInfo) {
                                // return outputDir + "/com/yrd/yljk/ggws/web/" + moduleName.replace(".", "/") + "/vo/" + tableInfo.getEntityName() + "VO.java";
                                // }
                                // },
                                new FileOutConfig("/templates/entityQueryVO.java.vm") {
                                    @Override
                                    public String outputFile(TableInfo tableInfo) {
                                        return outputDir + "/com/yrd/his/cloud/" + moduleName.replace(".", "/") + "/vo/" + tableInfo.getEntityName() + "QueryVO.java";
                                    }
                                }))
                        //
                )
                .setTemplate(
                        // 关闭默认 xml 生成，调整生成 至 根目录
                        new TemplateConfig().setXml(null)
                                .setController(null)
                                .setEntity("/templates/ygt_hospital_entity.java")
                                .setService("/templates/ygt_hospital_service.java")
                                .setServiceImpl("/templates/ygt_hospital_serviceImpl.java")
                        // 自定义模板配置，模板可以参考源码 /mybatis-plus/src/main/resources/template 使用 copy
                        // 至您项目 src/main/resources/template 目录下，模板名称也可自定义如下配置：
                        // .setController("...");
                        // .setEntity("...");
                        // .setMapper("...");
                        // .setXml("...");
                        // .setService("...");
                        // .setServiceImpl("...");
                )
                .setTemplateEngine(new MyVelocityTemplateEngine());
        mpg.execute();

        // 打印注入设置，这里演示模板里面怎么获取注入内容【可无】
        System.err.println(mpg.getCfg().getMap().get("abc"));
    }

    static List<String> ignoreFields = Arrays.asList("gmtCreate", "gmtModified");

    static class MyVelocityTemplateEngine extends VelocityTemplateEngine {
        @Override
        public Map<String, Object> getObjectMap(TableInfo tableInfo) {
            Map<String, Object> objectMap = super.getObjectMap(tableInfo);

            // tableInfo.setEntityName("Yb" + tableInfo.getEntityName());
            // tableInfo.setMapperName("Yb" + tableInfo.getMapperName());
            // objectMap.put("entity", tableInfo.getEntityName());

            tableInfo.getFields().forEach(f -> {
                String propertyName = f.getPropertyName();
                if (propertyName.length() > 1 && Character.isUpperCase(propertyName.charAt(1))) {
                    f.setPropertyName(propertyName.substring(0, 1) + Character.toLowerCase(propertyName.charAt(1)) + propertyName.substring(2));
                }
            });
            objectMap.put("tableAllFields", tableInfo.getFields().stream().filter(f -> !ignoreFields.contains(f.getPropertyName())).collect(Collectors.toList()));

            objectMap.put("tablePKTableField", tableInfo.getFields().stream().filter(f -> f.isKeyFlag()).findAny().orElse(null));

            objectMap.put("keyPropertyType", tableInfo.getFields().stream().filter(f -> f.isKeyFlag()).findAny().map(TableField::getPropertyType).orElse(null));

            objectMap.put("datetime", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));

            objectMap.put("serviceVariableName", tableInfo.getEntityName().substring(0, 1).toLowerCase() + tableInfo.getEntityName().substring(1) + "Service");
            objectMap.put("entityVariableName", "entity");

            //
            String[] uks = YGT_MED.tablesMap.get(tableInfo.getName());
            List  wheres = new ArrayList();
            for (String fieldName : uks) {
                String prop = StrUtil.toCamelCase(fieldName);
                wheres.add( fieldName + " =  #{entity." + prop + "}");
            }
            String whereCond = StringUtils.joinWith(" and ", wheres.toArray());
            objectMap.put("selectIdByUK", whereCond);

            return objectMap;
        }
    }

}
